package service

import (
	"encoding/json"
	"fmt"
	"github.com/cn-ygf/go-admin/internal/modular/system/dao"
	"github.com/cn-ygf/go-admin/internal/modular/system/model"
	"github.com/cn-ygf/go-admin/internal/modular/system/vo"
	"github.com/cn-ygf/go-admin/pkg/redis"
)

var (
	DictDataService = new(dictDataService)
)

const (
	DictCacheKey = "go_admin_dict_"
)

// dictDataService 后台字典
type dictDataService struct {
}

// GetByID 根据dictId查询字典数据
func (s dictDataService) GetByID(dictId int64) (*model.SysDictDatum, error) {
	return dao.SysDictDatum.Where(dao.SysDictDatum.DictCode.Eq(dictId)).First()
}

// GetValues 根据字典type获取值
func (s dictDataService) GetValues(typeName string) ([]*vo.SysDictData, error) {
	key := fmt.Sprintf("%s%s", DictCacheKey, typeName)
	jsonBuf, err := redis.GetBytes(key)
	if err != nil {
		values, err := s.GetValuesEx(typeName)
		if err != nil {
			systemLog.Errorln(err.Error())
			return nil, ServerError
		}
		l := len(values)
		result := make([]*vo.SysDictData, l)
		for index, item := range values {
			result[index] = &vo.SysDictData{
				DictCode:  item.DictCode,
				DictLabel: item.DictLabel,
				DictValue: item.DictValue,
				DictType:  item.DictType,
				CSSClass:  item.CSSClass,
				ListClass: item.ListClass,
			}
		}
		err = redis.SetJson(key, result)
		if err != nil {
			systemLog.Errorln(err.Error())
			return nil, ServerError
		}
		return result, nil
	}
	var result []*vo.SysDictData
	err = json.Unmarshal(jsonBuf, &result)
	if err != nil {
		systemLog.Errorln(err.Error())
		return nil, ServerError
	}
	return result, nil
}

// GetValuesEx 根据字典type获取值
func (s dictDataService) GetValuesEx(typeName string) ([]*model.SysDictDatum, error) {
	return dao.SysDictDatum.Where(dao.SysDictDatum.DictType.Eq(typeName)).
		Where(dao.SysDictDatum.Status.Eq("0")).
		Find()
}

// GetDictMaps 获取字典map结构
func (s dictDataService) GetDictMaps(typeName string) (map[string]string, error) {
	dicts, err := dao.SysDictDatum.Where(dao.SysDictDatum.DictType.Eq(typeName)).
		Where(dao.SysDictDatum.Status.Eq("0")).
		Find()
	if err != nil {
		systemLog.Errorln(err.Error())
		return nil, ServerError
	}
	r := make(map[string]string)
	for _, item := range dicts {
		r[item.DictValue] = item.DictLabel
	}
	return r, nil
}

// GetDictMapsEx 获取字典map结构
func (s dictDataService) GetDictMapsEx(typeName string) (map[string]string, error) {
	dicts, err := dao.SysDictDatum.Where(dao.SysDictDatum.DictType.Eq(typeName)).
		Where(dao.SysDictDatum.Status.Eq("0")).
		Find()
	if err != nil {
		systemLog.Errorln(err.Error())
		return nil, ServerError
	}
	r := make(map[string]string)
	for _, item := range dicts {
		r[item.DictLabel] = item.DictValue
	}
	return r, nil
}

// RefreshCache 刷新缓存
func (s dictDataService) RefreshCache() error {
	key := fmt.Sprintf("%s%s", DictCacheKey, "*")
	err := redis.BatDel(key)
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return nil
}

// RemoveCache 删除缓存
func (s dictDataService) RemoveCache(dictType string) error {
	key := fmt.Sprintf("%s%s", DictCacheKey, dictType)
	err := redis.Del(key)
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return nil
}

// QueryList 分页查询字典数据
func (s dictDataService) QueryList(req *vo.QueryDictDataListReq) ([]*model.SysDictDatum, int64, error) {
	var (
		u = dao.SysDictDatum
		d = u.Where()
	)
	if req.PageSize < 1 {
		req.PageSize = 10
	}
	if req.PageNum < 1 {
		req.PageNum = 1
	}
	if req.DictType != "" {
		d = d.Where(u.DictType.Eq(req.DictType))
	}
	if req.DictLabel != "" {
		d = d.Where(u.DictLabel.Eq(req.DictLabel))
	}
	if req.Status != "" {
		d = d.Where(u.Status.Eq(req.Status))
	}
	return d.FindByPage((req.PageNum-1)*req.PageSize, req.PageSize)
}

// Add 添加字典数据
func (s dictDataService) Add(req *vo.AddDictDataReq) error {
	u := dao.SysDictDatum
	newDictData := &model.SysDictDatum{
		DictSort:  req.DictSort,
		DictLabel: req.DictLabel,
		DictValue: req.DictValue,
		DictType:  req.DictType,
		CSSClass:  req.CSSClass,
		ListClass: req.ListClass,
		IsDefault: "N",
		Status:    req.Status,
		CreateBy:  req.CreateBy,
		Remark:    req.Remark,
	}
	err := u.Create(newDictData)
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	err = s.RemoveCache(req.DictType)
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return nil
}

// Update 修改字典数据
func (s dictDataService) Update(req *vo.EditDictDataReq) error {
	u := dao.SysDictDatum
	_, err := u.Where(u.DictCode.Eq(req.DictCode)).Updates(map[string]any{
		u.DictSort.ColumnName().String():  req.DictSort,
		u.DictLabel.ColumnName().String(): req.DictLabel,
		u.DictValue.ColumnName().String(): req.DictValue,
		u.DictType.ColumnName().String():  req.DictType,
		u.CSSClass.ColumnName().String():  req.CSSClass,
		u.ListClass.ColumnName().String(): req.ListClass,
		u.Status.ColumnName().String():    req.Status,
		u.Remark.ColumnName().String():    req.Remark,
		u.UpdateBy.ColumnName().String():  req.UpdateBy,
	})
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	err = s.RemoveCache(req.DictType)
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return nil
}

// Delete 删除字典数据
func (s dictDataService) Delete(dictCodeIds []int64) error {
	_, err := dao.SysDictDatum.Where(dao.SysDictDatum.DictCode.In(dictCodeIds...)).Delete()
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return err
}
